﻿using System;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;

namespace Flare
{
    public partial class MainWindow : Window, IPubFunctionMainWindow
    {
        #region Устаканено
        public MainWindow()
        {
            InitializeComponent();

            glob.kernel = (IPubFunctionMainWindow)this;

            System.Threading.Tasks.Task.Factory.StartNew(() => {
                Load();
            });
            ShowPage(typeof(Pages.StartPage));
        }

        public void Load() {
            if (File.Exists("flamedb.sdf") == false)
            {
                glob.kernel.Panic("Соединение с БД отсутствует", "Файл данных 'flamedb.sdf' не найден в директории программы", new System.IO.FileNotFoundException());
            }
            try
            {
                DB.Source.connection.Open();
            }
            catch (Exception ex)
            {
                glob.kernel.Panic(glob.PanicType.db_connect, ex);
            }
        }

        void CloseButton_Click(object sender, MouseButtonEventArgs e)
        {
            Application.Current.Shutdown();
            e.Handled = true;
        }

        void MinimizeButton_Click(object sender, MouseButtonEventArgs e)
        {
            this.WindowState = System.Windows.WindowState.Minimized;
            e.Handled = true;
        }

        void CollapseButton_Click(object sender, MouseButtonEventArgs e)
        {
            if (glob.IsCollapsed)
            {
                this.WindowState = System.Windows.WindowState.Maximized;
                glob.IsCollapsed = false;
            }
            else
            {
                this.WindowState = System.Windows.WindowState.Normal;
                glob.IsCollapsed = true;
            }
            e.Handled = true;
        }

        void ActiveHead_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        void findBlock_TextChanged(object sender, TextChangedEventArgs e)
        {
            this.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() =>
            {
                if (Slider.Content is IPubTypicalPage) (Slider.Content as IPubTypicalPage).SetSearchString(FindBlock.Text);
            }));
        }

        #endregion
        
        DispatcherFrame frame = new DispatcherFrame();
        void NoticeContent_MouseDown(object sender, MouseButtonEventArgs e)
        {
            frame.Continue = false;
            NoticeContent.Content = null;
        }

        public void ShowNotice(string _content)
        {
            this.Dispatcher.BeginInvoke((Action)(() =>
            {
                NoticeContent.Content = _content;
            }));

            Dispatcher.PushFrame(frame);
        }

        public void CreateFunctionalPanel(object[] _items)
        {
            if (FuncPanel == null) return;
            FuncPanel.Items.Clear();
            if (_items != null)
            {
                foreach (Object im in _items)
                {
                    FuncPanel.Items.Add(im);
                }
            }
        }

        public void RefreshResourceByName(string _resource_name)
        {
            if (Slider.Content != null && (Slider.Content as FrameworkElement).TryFindResource(_resource_name) != null)
            {
                ((Slider.Content as FrameworkElement).TryFindResource(_resource_name) as ObjectDataProvider).Refresh();
            }
        }

        public void ShowPage(Type page, object param = null, bool IsBack = false, bool replace_current = false)
        {
            object temp = null;
            try
            {
                temp = (param != null) ? Activator.CreateInstance(page, param) : Activator.CreateInstance(page);
            }
            catch (Exception ex)
            {
                ShowNotice("В данный момент указанный пункт меню не доступен. Попробуйте позже.");
                MyService.SendStackByMail(ex.StackTrace);
                return;
            }

            if ((temp is ITypicalPage) != true) return;

            if (Slider.Content is IDisposable)
            {
                (Slider.Content as IDisposable).Dispose();
            }

            this.CreateFunctionalPanel(null);

            ITypicalPage current_page = (ITypicalPage)temp;

            if (current_page is IPubTypicalPage)
            {
                FindBlock.Visibility = System.Windows.Visibility.Visible;
                ((IPubTypicalPage)current_page).SetSearchString(FindBlock.Text);
                ((IPubTypicalPage)current_page).CreateStartMenu();
            }
            else
            {
                FindBlock.Visibility = System.Windows.Visibility.Collapsed;
            }

            Slider.Content = current_page;

            if (IsBack == false)
            {
                if (replace_current)
                {
                    int last_index = RepeatMenu.Items.Count - 1;
                    RepeatMenu.Items.RemoveAt(last_index);
                }
                RepeatMenu.Items.Add(new Repeater()
                {
                    page_struct = page,
                    Caption = current_page.name,
                    param = param
                });
            }
        }

        public void Panic(string _header, string _content, Exception ex)
        {
            if (ex != null)
            {
                Debug.WriteLine(ex.Message + "\n\n" + ex.StackTrace);
                MyService.SendStackByMail(ex.Message + "\n\n" + ex.StackTrace);
            }

            DispatcherFrame frame = new DispatcherFrame();
            this.Dispatcher.Invoke((Action)(() =>
            {
                this.Content = new Pages.BlueWindow(_header, _content);
            }));

            Dispatcher.PushFrame(frame);
        }

        public void Panic(glob.PanicType panic, Exception ex)
        {
            switch (panic)
            {
                case glob.PanicType.db_connect:
                    this.Panic("Что-то не так с базой данных?!!", "База данных не отвечает. Возможно идет процесс перезагрузки. Попробуйте позже", ex);
                    break;

                case glob.PanicType.sql:
                    this.Panic("Что-то не так с базой данных?!!", "В базе данных обнаружены ошибки. Мы занимаемся их устранением. Попробуйте позже", ex);
                    break;

                case glob.PanicType.access:
                    this.Panic("Ошибка доступа в программу :(", "Судя по имеющимся данным, Вам не разрешен доступ в программу. Обратитесь к разработчику.", ex);
                    break;

                case glob.PanicType.other:
                    this.Panic("Очень странно :(", "В программе обнаружена неисправимая ошибка. Приложение требуется перезапустить", ex);
                    break;
            };
        }

        private void RepeatMenu_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (RepeatMenu.IsMouseOver)
            {
                int select_id = RepeatMenu.SelectedIndex;
                int total_count = RepeatMenu.Items.Count - 1;

                for (int i = total_count; i > select_id; i--)
                {
                    RepeatMenu.Items.RemoveAt(i);
                }

                var info = (Repeater)(RepeatMenu.SelectedValue);
                ShowPage(info.page_struct, info.param, true);
            }
        }

        struct Repeater
        {
            public Type page_struct { get; set; }
            public string Caption { get; set; }
            public object param { get; set; }
        }
    }

}
